package sample.Utils

import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kt.Utils.colRowNum
import kt.Utils.getForestMapUrl
import kt.Utils.getRegionMAllLv
import kt.Utils.getRegionMAllLvTianDi
import kt.bean.MapLayerBean
import okhttp3.*
import sample.bean.DownFileBean
import sample.bean.Point
import java.io.File
import java.io.IOException
import java.lang.Exception
import java.lang.ref.SoftReference
import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.atomic.AtomicReference

class DownMap {
    private val okHttpClient = OkHttpClient()
    var mRootFileDir = "D:\\TestDta\\mao"
    private var downIndex = AtomicLong()
    private val mutex = Mutex()
    var isInterrupt = false
    var isStartDown = false
    var mScope: Job? = null
    suspend fun startDown(
        listRange: MutableList<Point>,
        level: Int,
        urlId: String,
        name: String,
        downListener: (downNum: Long, allCount: Long) -> Unit
    ) {
        downIndex.set(0)
        val colRowRange = getRegionMAllLv(listRange, level)
        val allContent = AtomicReference(colRowNum(colRowRange))
        val downFile = mutableListOf<DownFileBean>()
        val asyncResult = mutableListOf<Deferred<Any?>>()
        mScope = GlobalScope.launch {
            isStartDown = true
            isInterrupt = false
            withContext(Dispatchers.IO) {
                colRowRange.forEachIndexed { index, arrayList ->
                    val colMin = arrayList[0]
                    val rowMin = arrayList[1]
                    val colMax = arrayList[2]
                    val rowMax = arrayList[3]
                    for (col in colMin..colMax) {
                        for (row in rowMin..rowMax) {
                            while (asyncResult.size >= 10000) {
                                asyncResult[asyncResult.size - 1].await()
                                asyncResult.clear()
                            }
                            val syncs = async {
                                val response = SoftReference(
                                    Request.Builder()
                                        .url(getForestMapUrl(index, col, row, urlId))
                                        .build()
                                )
                                try {
                                    val re = okHttpClient.newCall(response.get()!!).execute()
                                    re.body?.let {
                                        val mapLayBean =
                                            MapLayerBean(
                                                (index).toString(),
                                                col.toString(),
                                                row.toString(),
                                                it.bytes()
                                            )
                                        savePicV2(mapLayBean, name)
                                    }
                                } catch (e: Exception) {
                                    downFile.add(DownFileBean(index, col, row))
                                } finally {
                                    downIndex.addAndGet(1)
                                }
                            }
                            asyncResult.add(syncs)
                        }
                    }
                }
            }
            isStartDown = false
        }
        while (downIndex.get() != allContent.get() || isInterrupt) {
            delay(2000)
            println("i = ${downIndex.get()}, all = ${allContent.get()}, ss = ${asyncResult.size}")
            downListener(downIndex.get(), allContent.get())
        }
        println("FileNum:${downFile.size}")
    }

    /**
     * 林地小班下载
     */
    suspend fun startDownLinDi(
        listRange: MutableList<Point>,
        level: Int,
        urlId: String,
        name: String,
        downListener: (downNum: Long, allCount: Long) -> Unit
    ) {
        downIndex.set(0)
        val colRowRange = getRegionMAllLv(listRange, level)
        val allContent = AtomicReference(colRowNum(colRowRange))
        val downFile = mutableListOf<DownFileBean>()
        val asyncResult = mutableListOf<Deferred<Any?>>()
        mScope = GlobalScope.launch {
            isStartDown = true
            isInterrupt = false
            withContext(Dispatchers.IO) {
                colRowRange.forEachIndexed { index, arrayList ->
                    val colMin = arrayList[0]
                    val rowMin = arrayList[1]
                    val colMax = arrayList[2]
                    val rowMax = arrayList[3]
                    for (col in colMin..colMax) {
                        for (row in rowMin..rowMax) {
                            while (asyncResult.size >= 10000) {
                                asyncResult[asyncResult.size - 1].await()
                                asyncResult.clear()
                            }
                            val syncs = async {
                                val response = SoftReference(
                                    Request.Builder()
                                        .url(getForestMapUrl(index + 1, col, row, urlId))
                                        .build()
                                )
                                try {
                                    val re = okHttpClient.newCall(response.get()!!).execute()
                                    re.body?.let {
                                        val mapLayBean =
                                            MapLayerBean(
                                                (index).toString(),
                                                col.toString(),
                                                row.toString(),
                                                it.bytes()
                                            )
                                        savePicV2(mapLayBean, name)
                                    }
                                } catch (e: Exception) {
                                    downFile.add(DownFileBean(index, col, row))
                                } finally {
                                    downIndex.addAndGet(1)
                                }
                            }
                            asyncResult.add(syncs)
                        }
                    }
                }
            }
            isStartDown = false
        }
        while (downIndex.get() != allContent.get() || isInterrupt) {
            delay(2000)
            println("i = ${downIndex.get()}, all = ${allContent.get()}, ss = ${asyncResult.size}")
            downListener(downIndex.get(), allContent.get())
        }
        println("FileNum:${downFile.size}")
    }

    suspend fun startDownTianDi(
        listRange: MutableList<Point>,
        level: Int,
        downListener: (downNum: Long, allCount: Long) -> Unit
    ) {
        downIndex.set(0)
        val colRowRange = getRegionMAllLvTianDi(listRange, level)
        val allContent = AtomicReference(colRowNum(colRowRange))
        val downFile = mutableListOf<DownFileBean>()
        val asyncResult = mutableListOf<Deferred<Any?>>()
        mScope = GlobalScope.launch {
            isStartDown = true
            isInterrupt = false
            withContext(Dispatchers.IO) {
                colRowRange.forEachIndexed { index, arrayList ->
                    val colMin = arrayList[0]
                    val rowMin = arrayList[1]
                    val colMax = arrayList[2]
                    val rowMax = arrayList[3]
                    for (col in colMin..colMax) {
                        for (row in rowMin..rowMax) {
                            while (asyncResult.size >= 10000) {
                                asyncResult[asyncResult.size - 1].await()
                                asyncResult.clear()
                            }
                            val syncs = async {
                                val response = SoftReference(
                                    Request.Builder()
                                        .url(getForestMapUrl(index + 1, col, row, "天地图"))
                                        .build()
                                )
                                try {
                                    val re = okHttpClient.newCall(response.get()!!).execute()
                                    println(response.get()!!)
                                    re.body?.let {
                                        val mapLayBean =
                                            MapLayerBean(
                                                (index + 1).toString(),
                                                col.toString(),
                                                row.toString(),
                                                it.bytes()
                                            )
                                        savePicV2(mapLayBean, "天地图")
                                    }
                                } catch (e: Exception) {
                                    downFile.add(DownFileBean(index, col, row))
                                } finally {
                                    downIndex.addAndGet(1)
                                }
                            }
                            asyncResult.add(syncs)
                        }
                    }
                }
            }
            isStartDown = false
        }
        while (downIndex.get() != allContent.get() || isInterrupt) {
            delay(2000)
            println("i = ${downIndex.get()}, all = ${allContent.get()}, ss = ${asyncResult.size}")
            downListener(downIndex.get(), allContent.get())
        }
        println("FileNum:${downFile.size}")
    }

    private fun savePicV2(mapLayBean: MapLayerBean, name: String) {
        val fileName = when (name) {
            "新疆2019年影像" -> "xjImages2019"
            "新疆2018年影像" -> "xjImages2018"
            "新疆2017年影像" -> "xjImages2017"
            "新疆2016年影像" -> "xjImages2016"
            "新疆2013年影像" -> "xjImages2013"
            "林地小班2019" -> "ldForest2019"
            "林地小班2018" -> "ldForest2018"
            "天地图" -> "TianDiTu"
            else -> name
        }

        val filePath = File("${mRootFileDir}\\${fileName}\\${mapLayBean.level}\\${mapLayBean.col}")
        if (!filePath.exists()) {
            filePath.mkdirs()
        }

        val fileMapImages = File("${filePath.path}\\${mapLayBean.row}.png")
        fileMapImages.createNewFile()
        println(mapLayBean.toString())
        fileMapImages.writeBytes(mapLayBean.images)
    }

    fun testUrlConnect(listener: (isConnect: Boolean) -> Unit) {
        okHttpClient.newCall(
            Request.Builder().url(getForestMapUrl(0, 1, 0, "84256fab-fafa-4fd4-bcb5-d319a3f2e4b6")).build()
        ).enqueue(
            object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    listener(false)
                }

                override fun onResponse(call: Call, response: Response) {
                    listener(true)
                }

            }
        )
    }
}